/*
//	machdep.cc
//
//	Machine dependencies checker
//
//	(C) R.P.Bellis 1993
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif

void word_sizes(FILE *f)
{
	fprintf(f, "#define MACH_SHORT_SIZE %ld\n", (long)sizeof(short));
	fprintf(f, "#define MACH_INT_SIZE %ld\n", (long)sizeof(int));
	fprintf(f, "#define MACH_LONG_SIZE %ld\n", (long)sizeof(long));
	fprintf(f, "#define MACH_FLOAT_SIZE %ld\n", (long)sizeof(float));
	fprintf(f, "#define MACH_DOUBLE_SIZE %ld\n", (long)sizeof(double));
}

void byte_order(FILE *f)
{
	union {
		struct {
			unsigned char	field1;
			unsigned char	field2;
		} bytes;
		unsigned int		value;
	} tmp;

	tmp.value = 0;
	tmp.bytes.field1 = 1;

	if (tmp.value == 1) {
		fprintf(f, "#define MACH_BYTE_ORDER_LSB_FIRST\n");
	} else {
		fprintf(f, "#define MACH_BYTE_ORDER_MSB_FIRST\n");
	}
}

void bitfield_order(FILE *f)
{
	union {
		struct {
			unsigned int	field1 : 1;
			unsigned int	dummys : 6;
			unsigned int	field2 : 1;
		} bits;
		unsigned int		value;
	} tmp;

	tmp.value = 0;
	tmp.bits.field1 = 1;

	if (tmp.value == 1) {
		fprintf(f, "#define MACH_BITFIELDS_LSB_FIRST\n");
	} else {
		fprintf(f, "#define MACH_BITFIELDS_MSB_FIRST\n");
	}
}

void stddefs(FILE *f)
{
	fprintf(f, "#ifndef EXIT_SUCCESS\n");
	fprintf(f, "#define EXIT_SUCCESS 0\n");
	fprintf(f, "#define EXIT_FAILURE 1\n");
	fprintf(f, "#endif\n\n");
}

int main(int argc, char *argv[])
{
	FILE		*f;
	char		*path, *guard, *p;
	time_t		tp;
	int		i, len;

	if (argc != 2) {
		fprintf(stderr, "usage: machdep <outfile>\n");
		return EXIT_FAILURE;
	}

	/* Generate guard macro name */
	path = argv[1];
	len = strlen(path);
	p = guard = malloc(len + 5);

	*p++ = '_'; *p++ = '_';
	for (i = 0; i < len; ++i) {
		char		c = path[i];
		if (isalpha(c)) {
			*p++ = tolower(c);
		} else {
			*p++ = '_';
		}
	}
	*p++ = '_'; *p++ = '_'; *p++ = '\0';

	/* Open output stream */
	if ((f = fopen(path, "w")) == NULL) {
		perror("fopen");
		return EXIT_FAILURE;
	}

	/* Add head of output file */
	tp = time(NULL);
	fprintf(f, "/*\n");
	fprintf(f, " *\tmachdep.h generated by machdep at %s", ctime(&tp));
	fprintf(f, " */\n\n");
	fprintf(f, "#ifndef %s\n", guard);
	fprintf(f, "#define %s\n\n", guard);

	/* Call the determination functions */
	stddefs(f);
	word_sizes(f);
	byte_order(f);
	bitfield_order(f);

	/* Add tail of output file */
	fprintf(f, "\n#endif /* %s */\n", guard);

	return EXIT_SUCCESS;
}
